using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;


namespace GameEditor.Common.Designer
{


    public sealed class DesignerCommands
    {
        private DesignerCommands()
        {
        }
        public delegate void Command(DesignerPanel panel, Control control);

        public static int Truncate(int a, int b)
        {
            return (int)(Math.Floor(1.0f * a / b + 0.5) * b);
        }


        public static void AlignToGrid(DesignerPanel panel, Control obj)
        {
            Size cellSize = panel.GridSize;
            Rectangle refRect, g;

            refRect = g = obj.TransformedGeometry;

            //g.X = (g.X / cellSize.Width) * cellSize.Width;
            //g.Y = (g.Y / cellSize.Height) * cellSize.Height;

            g.X = Truncate(g.X, cellSize.Width);
            g.Y = Truncate(g.Y, cellSize.Height);
            g.Width = Truncate(g.Width, cellSize.Width);
            g.Height = Truncate(g.Height, cellSize.Height);

            //g.Width = Math.Max(cellSize.Width, (g.Width / cellSize.Width) * cellSize.Width);
            //g.Height = Math.Max(cellSize.Width, (g.Height / cellSize.Height) * cellSize.Height);

            Rectangle rect = obj.Geometry;
            rect.X += g.X - refRect.X;
            rect.Y += g.Y - refRect.Y;
            rect.Width += g.Width - refRect.Width;
            rect.Height += g.Height - refRect.Height;

            obj.Geometry = rect;            



            return;
            //PointF pos = obj.Position;
            //SizeF size = obj.Size;
            ////caculate the coordinates to fit the grid
            //float cellHeight = 1.0f / (1 + panel.HGridLines);
            //float cellWidth = 1.0f / (1 + panel.VGridLines);
            //pos.X = cellWidth * (int)(0.5f + pos.X / cellWidth);
            //pos.Y = cellHeight * (int)(0.5f + pos.Y / cellHeight);


            //float newWidth = cellWidth * (int)(0.5f + size.Width / cellWidth);
            //float newHeight = cellHeight * (int)(0.5f + size.Height / cellHeight);


            //if (panel.AlignToGrid)
            //{
            //    if (newWidth < cellWidth)
            //        newWidth = cellWidth;
            //    if (newHeight < cellHeight)
            //        newHeight = cellHeight;
            //}
            //if (Math.Abs(newWidth * panel.Width) > 3)
            //    size.Width = newWidth;

            //if (Math.Abs(newHeight * panel.Height) > 3)
            //    size.Height = newHeight;

            //obj.Position = pos;
            //obj.Size = size;
        }
        public static void SendToBack(DesignerPanel panel, Control control)
        {
            //the controls were sorted by zorder, from great to less
            //so bring to front is just find the previous control,
            // and replace the zorder and the position
            List<Control> controls = null;
            if (control.Parent == null)
                return;
            controls = (control.Parent as Designer.Window)._Children;
            
            int idx = controls.IndexOf(control);
            if (idx == -1)// already the first one
                return;
            if (controls.Count <= 1)
                return;
            int prevIdx = idx - 1;

            Control prev=controls[prevIdx];
            //swap the zorder
            int zorder = control.ZOrder;
            control.ZOrder = prev.ZOrder;
            prev.ZOrder = zorder;
            //swap the position
            controls[prevIdx] = control;
            controls[idx] = prev;
        }
        public static void BringToFront(DesignerPanel panel, Control control)
        {
            //the controls were sorted by zorder, from great to less
            //send to back is similar to the SendToBack, but swap with the succeeding control
            // and exchange the zorder and the position
            List<Control> controls = null;
            if (control.Parent == null)
                return;
            controls = (control.Parent as Designer.Window)._Children;

            int idx = controls.IndexOf(control);
            if (idx == controls.Count - 1)// already the last one
                return;
            if (controls.Count <= 1)
                return;
            int succIdx = idx + 1;
            Control succ = controls[succIdx];
            //swap the zorder
            int zorder = control.ZOrder;
            control.ZOrder = succ.ZOrder;
            succ.ZOrder = zorder;
            //swap the position
            controls[succIdx] = control;
            controls[idx] = succ;
        }

        public static void NotifyGeometryChanged(DesignerPanel panel, Control control)
        {
            control.OnGeometryChanged();
        }
        public static void LockControl(DesignerPanel panel, Control control)
        {
            control.Locked = true;
        }
        public static void UnlockControl(DesignerPanel panel, Control control)
        {
            control.Locked = false;
        }
        public static void HideSelection(DesignerPanel panel, Control control)
        {
            control.Visible = false;
        }
    }
}
